#pragma once

#include "string"
#include "glad/glad.h"
#include "GLFW/glfw3.h"

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#include "GlLoader.h"
#include "Log.h"

namespace GL
{

    struct ObjectData
    {
        float l; // position left
        float r; // position right
        float t; // position top
        float b; // position bottom
        float f; // position far
        float n; // position near
        float R; // red
        float G; // green
        float B; // blue
        float A; // alipa
        float D; // deep
        float W; // w
    };

    struct TransformData
    {
        float x;
        float y;
        float z;
        float rx;
        float ry;
        float rz;
        float sx;
        float sy;
        float sz;

        TransformData(float x = 0.0f,
                      float y = 0.0f,
                      float z = 0.0f,
                      float rx = 0.0f,
                      float ry = 0.0f,
                      float rz = 0.0f,
                      float sx = 1.0f,
                      float sy = 1.0f,
                      float sz = 1.0f) : x(x), y(y), z(z), rx(rx), ry(ry), rz(rz), sx(sx), sy(sy), sz(sz) {}
    };

    class Renderer
    {
    public:
        Renderer(){};
        ~Renderer();
        virtual void Awake(ObjectData &data) = 0;
        virtual void Start();

        virtual void CreateVertexBuffer(float vertexs[]) = 0;
        virtual void CreateIndexesBuffer(unsigned int indexes[]) = 0;
        int CreateShader(const std::string shaderSource, int type);
        int CreateVertexShader(const std::string shaderSource);
        int CreateFragmentShader(const std::string shaderSource);
        int CreateProgram(int vertexShader, int fragmentShader);
        virtual void Render() = 0;
        void useProgram();
        int GetAttributeLocation(int program, const std::string name);
        int GetUniformLocation(int program, const std::string &name);

        virtual void SetTexture(std::string ImageUrl) = 0;
        void ReadShaderSource(const std::string &sourceUrl);
        void SetTranslate(glm::vec3 &pos);
        void SetRotate(glm::vec3 &angle);
        void SetScale(glm::vec3 &scale);
        void SetMatrix();
        void SetViewMatrix(glm::mat4 &view);

        void SetVec3(const std::string &attributeName, glm::vec3 &vec);

    protected:
        /*
            顶点集合，包括 位置、 颜色 、纹理  3 ，3 ，2
        */

        // 变换数据

        TransformData transformData;

        std::string VertexSource;
        std::string FragmentSource;
        // 当前渲染器的顶点缓冲
        unsigned int VertexArray;
        unsigned int texture[16];
        int textureIndex = 0;

        glm::mat4 viewMatrix = glm::mat4(1.0f);
        glm::mat4 modelMatrix = glm::mat4(1.0f);
        glm::mat4 projectionMatrix = glm::mat4(1.0f);
        //
        unsigned int Program;
    };

}